package ia.robot.app;

import java.io.Serializable;
import java.util.Random;

import ia.robot.graphics.Bitmap;
import ia.robot.graphics.Textures;

/**
 * Clase que representa un tablero.
 * 
 * @author Jaime A. Corrales Gonzalez
 * @author Alejandro Tejera Perez
 */
public class Board implements Cloneable, Serializable {

	private static final long serialVersionUID = 1L;

	private int width;
	private int height;
	private int tab[][];
	private int botDir = Point.SOUTH;

	private Point botPos = null;
	private Point destPos = null;

	/**
	 * Constructor dados la anchura y altura del tablero.
	 * 
	 * @param width
	 *            - Anchura del tablero.
	 * @param height
	 *            - Altura del tablero.
	 */
	public Board(int width, int height) {
		this.width = width;
		this.height = height;

		this.tab = new int[width][height];

		for (int x = 0; x < width; x++)
			for (int y = 0; y < height; y++)
				tab[x][y] = Textures.TILE_GRASS;

		this.botPos = null;
		this.destPos = null;
	}

	// Getters & Setters.

	/**
	 * 
	 * @return
	 */
	public int getBotDir() {
		return this.botDir;
	}

	/**
	 * 
	 * @return
	 */
	public Point getBotPos() {
		return this.botPos;
	}

	/**
	 * 
	 * @return
	 */
	public Point getDestPos() {
		return this.destPos;
	}

	/**
	 * 
	 * @return
	 */
	public int getWidth() {
		return this.width;
	}

	/**
	 * 
	 * @return
	 */
	public int getHeight() {
		return this.height;
	}

	/**
	 * 
	 * @param botDir
	 */
	public void setBotDir(int botDir) {
		this.botDir = botDir;
	}

	/**
	 * 
	 * @param botPos
	 */
	public void setBotPos(Point botPos) {
		this.botPos = botPos;
	}

	/**
	 * 
	 * @param destPos
	 */
	public void setDestPos(Point destPos) {
		this.destPos = destPos;
	}
	
	/**
	 * 
	 * @param p
	 * @param tile
	 */
	public void setContent(Point p, int tile) {
		try {
			tab[p.getX()][p.getY()] = tile;
		} catch (Exception e) {

		}
	}

	// Funciones de consulta.

	/**
	 * Funcion de consulta a una casilla
	 * 
	 * @param p
	 *            - Punto del tablero que consultar
	 * @return - Contenido de la casilla del tablero
	 */
	public int getContent(Point p) {
		try {
			return this.tab[p.getX()][p.getY()];
		} catch (ArrayIndexOutOfBoundsException e) {
			return Textures.TILE_STONE;
		}
	}

	// Funciones de dibujo.

	/**
	 * Funcion que devuelve la representacion visual del tablero.
	 * 
	 * @return Representacion visual del tablero.
	 */
	public Bitmap getBitmap() {
		Bitmap img = new Bitmap(width * Textures.TILE_WIDTH, height
				* Textures.TILE_HEIGHT);
		Bitmap temp;

		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				temp = Textures.getBitmap(tab[x][y]);
				img.draw(temp, x * Textures.TILE_WIDTH, y
						* Textures.TILE_HEIGHT, 0, 0, Textures.TILE_WIDTH,
						Textures.TILE_HEIGHT);
			}
		}

		if (destPos != null) {
			temp = Textures.getBitmap(Textures.TILE_GOAL);
			img.draw(temp, destPos.getX() * Textures.TILE_WIDTH, destPos.getY()
					* Textures.TILE_HEIGHT, 0, 0, Textures.TILE_WIDTH,
					Textures.TILE_HEIGHT);
		}

		if (botPos != null) {
			temp = Textures.getBitmap(Textures.TILE_BOT_NORTH + botDir);
			img.draw(temp, botPos.getX() * Textures.TILE_WIDTH, botPos.getY()
					* Textures.TILE_HEIGHT, 0, 0, Textures.TILE_WIDTH,
					Textures.TILE_HEIGHT);
		}

		return img;
	}

	// Funciones utiles.

	public Board clone() {
		Board ret = new Board(this.width, this.height);

		for (int x = 0; x < this.width; x++)
			for (int y = 0; y < this.height; y++)
				ret.tab[x][y] = this.tab[x][y];

		ret.botDir = this.botDir;
		ret.botPos = this.botPos.clone();
		ret.destPos = this.destPos.clone();

		return ret;
	}

	public void randomize() {
		Random rng = new Random(System.nanoTime());
		int x, y;

		for (x = 0; x < width; x++) {
			for (y = 0; y < height; y++) {
				int p = rng.nextInt(100);

				if (p < 75)
					tab[x][y] = Textures.TILE_GRASS;
				else
					tab[x][y] = Textures.TILE_STONE;
			}
		}
		
		botDir = 2;
		botPos = null;
		destPos = null;
	}
}
